package ru.ifmo.itmokis;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import ru.ifmo.itmokis.domain.Order;
import ru.ifmo.itmokis.domain.OrderedProduct;
import ru.ifmo.itmokis.sim.Clock;
import ru.ifmo.itmokis.util.DataContext;

/**
 *
 * @author Ivan Stepuk
 */
public class MiniServer {

    public static final int PORT = 5511;
    private Clock clock;
    private DataContext dataContext;
    private Facade facade;
    // ^ Dependencies ^
    private Server jetty = new Server(PORT);

    public MiniServer(Clock clock, Facade facade, DataContext dataContext) {
        this.clock = clock;
        this.facade = facade;
        this.dataContext = dataContext;
    }

    public void start() throws Exception {

        ContextHandler newOrder = new ContextHandler();
        newOrder.setContextPath("/neworder");
        newOrder.setResourceBase(".");
        newOrder.setClassLoader(Thread.currentThread().getContextClassLoader());
        newOrder.setHandler(new NewOrderHandler());

        ContextHandler orderInfo = new ContextHandler();
        orderInfo.setContextPath("/orderinfo");
        orderInfo.setResourceBase(".");
        orderInfo.setClassLoader(Thread.currentThread().getContextClassLoader());
        orderInfo.setHandler(new OrderInfoHandler());

        ContextHandler def = new ContextHandler();
        def.setContextPath("/");
        def.setResourceBase(".");
        def.setClassLoader(Thread.currentThread().getContextClassLoader());
        def.setHandler(new DefaultHandler());

        HandlerList handlers = new HandlerList();
        handlers.addHandler(newOrder);
        handlers.addHandler(orderInfo);
        handlers.addHandler(def);

        jetty.setHandler(handlers);
        jetty.start();
    }

    public class DefaultHandler extends AbstractHandler {

        @Override
        public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
            response.setContentType("text/html;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            baseRequest.setHandled(true);
            response.getWriter().println("<h1>Manual (usage)</h1>");
            response.getWriter().println("<p>To add new order use something like this:");
            response.getWriter().println("/neworder?x=1&y=1&z=1&urgent=0</p>");
            response.getWriter().println("<p>To retrieve order info:");
            response.getWriter().println("/orderinfo?id=1</p>");
        }
    }

    public class OrderInfoHandler extends AbstractHandler {

        @Override
        public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {

            Order o = dataContext.getOrderById(Integer.parseInt(request.getParameter("id")));

            response.setContentType("text/html;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            baseRequest.setHandled(true);
            response.getWriter().println("<h1>Order information</h1>");
            response.getWriter().println("<p>Id: " + o.getId() + "</p>");
            response.getWriter().println("<p>Type: " + o.getType() + "</p>");
            response.getWriter().println("<p>Customer: " + o.getCustomer() + "</p>");
            response.getWriter().println("<p>Status: " + o.getStatus() + "</p>");
            response.getWriter().println("<p>Deadline: " + o.getDeadline() + "</p>");
            response.getWriter().println("<p>Total products: " + o.getTotalProducts() + "</p>");
            response.getWriter().println("<p>Completed products: " + o.getCompletedProducts() + "</p>");
            response.getWriter().println("<p>Completion time: " + o.getCompletionTime() + "</p>");

        }
    }

    public class NewOrderHandler extends AbstractHandler {

        @Override
        public void handle(String target, Request baseRequest,
                HttpServletRequest request, HttpServletResponse response)
                throws IOException, ServletException {

            int xs = Integer.parseInt(request.getParameter("x"));
            int ys = Integer.parseInt(request.getParameter("y"));
            int zs = Integer.parseInt(request.getParameter("z"));
            int urgent = Integer.parseInt(request.getParameter("urgent"));
            Order.Type type;
            if (urgent == 0) {
                type = Order.Type.STANDARD;
            } else {
                type = Order.Type.URGENT;
            }

            // Generate order
            Order order = new Order();
            order.setApprovementTime(clock.getCurrentTime());
            order.setCompletedProducts(0);
            order.setCustomer(dataContext.getUserById(1));
            order.setStatus(Order.Status.APPROVED);
            order.setTotalProducts(xs + ys + zs);
            order.setType(type);

            // Generate ordered products
            List<OrderedProduct> products = new ArrayList<OrderedProduct>();
            for (int i = 0; i < xs; i++) {
                OrderedProduct op = new OrderedProduct();
                op.setOrder(order);
                op.setProduct(dataContext.getProductByName("X"));
                products.add(op);
            }
            for (int i = 0; i < ys; i++) {
                OrderedProduct op = new OrderedProduct();
                op.setOrder(order);
                op.setProduct(dataContext.getProductByName("Y"));
                products.add(op);
            }
            for (int i = 0; i < zs; i++) {
                OrderedProduct op = new OrderedProduct();
                op.setOrder(order);
                op.setProduct(dataContext.getProductByName("Z"));
                products.add(op);
            }

            // Move data to Facade
            facade.registerNewOrder(order, products);

            // Responce

            response.setContentType("text/html;charset=utf-8");
            response.setStatus(HttpServletResponse.SC_OK);
            baseRequest.setHandled(true);
            response.getWriter().println("<h1>Order approved</h1>");
        }
    }
}
